package com.star.ms.admin.controller;
import com.star.ms.admin.service.user.RoleService;
import com.star.ms.admin.service.user.UserService;
import com.star.ms.common.entity.RestResponse;
import com.star.ms.common.entity.api.OssUploadResult;
import com.star.ms.common.entity.user.User;
import com.star.ms.common.service.OssService;
import com.star.ms.common.vo.UserAddressCodeVo;
import com.star.ms.admin.service.impl.address.AddressServiceImpl;
import com.star.ms.common.vo.UserProvinceCountVo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.Map;

/*
 * @Author: Uni
 * @Time: 2022/5/12
 * @TODO
 */
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private OssService ossService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private AddressServiceImpl addressService;
    @PostMapping("provinces")
    public String getAllAddress(){
        return RestResponse.success(addressService.getProvinces()).toString();
    }

    @PostMapping("citiesby")
    public String getCityByProvinceCode(String provinceCode){
        return RestResponse.success(
                addressService.getCityByProvinceCode(provinceCode)).toString();
    }
    @PostMapping("/areaby")
    public String getAreaByCityCode(String cityCode){
        return RestResponse.success(
                addressService.getAreaByCityCode(cityCode)).toString();
    }
    @PostMapping("/addressby")
    public String getAddressByCode(String userCode){
        Map<String, String> map = addressService.getAddressByCode(userCode);
        return map == null ?
                RestResponse.fail("获取用户账号为[" + userCode +  "]的地址失败").toString()
                : RestResponse.success(map).toString();
    }
    @PostMapping("/insert")
    public RestResponse<String> insertUser(User user, UserAddressCodeVo addressCodeVo){
        // 进行注册
        User registerUser = userService.insertUser(user, addressCodeVo);
        return registerUser != null  ? RestResponse.success("插入成功!") :
                RestResponse.fail("插入失败.");
    }
    @PostMapping("/register")
    public RestResponse<String> register(User user, String emailCode){
        // 验证码不正确直接返回
        if(!userService.verifyEmailCode(user, emailCode))
            return RestResponse.fail("验证码错误!");
        // 进行注册
        return userService.register(user) != null ?
                RestResponse.success("注册成功!") :
                    RestResponse.fail("注册失败");
    }
    // 发送邮箱验证码，用于注册账号、修改密码、修改邮箱
    @PostMapping("/sendcode")
    public RestResponse<String> sendCode(User user, HttpSession session){
        //修改密码时发送验证码
        if(user == null || user.getEmail() == null){
            user =(User) session.getAttribute("loginUser");
        }
        return userService.sendRegisterEmail(user) ?
                RestResponse.success("验证码发送成功!") :
                    RestResponse.fail("验证码发送失败.");
    }
    // 发送邮箱验证码，用于找回账号
    @PostMapping("/sendEmailCode")
    public RestResponse<String> sendEmailCode(User user){
        return userService.sendRetrieveEmail(user) ?
                RestResponse.success("验证码发送成功!") :
                    RestResponse.fail("验证码发送失败.");
    }
    @PostMapping("/sendCaptchaToUpdate")
    public RestResponse<String> sendCaptchaToUpdate(User user, HttpSession session){
        User loginUser =(User) session.getAttribute("loginUser");
        // 限制修改的邮箱不能和之前的一样
        if(loginUser.getEmail().equals(user.getEmail()))
            return RestResponse.fail("修改的邮箱不能和之前的相同");
        // 限制邮箱必须是不存在的
        if(userService.hasExisted(user.getEmail()))
            return RestResponse.fail("该邮箱已存在");
        user.setUsercode(loginUser.getUsercode());
        return userService.sendRegisterEmail(user) ?
                RestResponse.success("验证码发送成功!"):
                    RestResponse.fail("验证码发送失败.");
    }
    @PostMapping("/sendCodeWithVerification")
    public String sendCodeWithVerification(User user, HttpSession session){
        User loginUser = (User) session.getAttribute("loginUser");
        // 检验用户输入的邮箱是否和当前登录的用户匹配
        if(!user.getEmail().equals(loginUser.getEmail())){
            return RestResponse.fail("用户当前输入的邮箱和登录用户的邮箱不匹配.").toString();
        }
        user.setUsercode(loginUser.getUsercode());
        // 发送邮件
        return  userService.sendRegisterEmail(user) ?
                RestResponse.success("验证码发送成功!").toString():
                RestResponse.fail("验证码发送失败.").toString();
    }
    @PostMapping("/login")
    public String login(User user, Integer remember, HttpSession session, HttpServletResponse response){
        User loginUser = userService.login(user);
        if(loginUser == null)
            return RestResponse.fail("登录失败，请检查用户名和密码是否匹配").toString();
        else {
            // 记录用户信息
            session.setAttribute("loginUser", loginUser);
            // 使用 Cookie 实现下次自动登录
            if(remember!=null && remember == 1) {
                Cookie ck_code = new Cookie("usercode", user.getUsercode());
                Cookie ck_pw = new Cookie("password", user.getPassword());
                int day3 = 60 * 60 * 24 * 3;
                ck_code.setMaxAge(day3);
                ck_pw.setMaxAge(day3);
                response.addCookie(ck_code);
                response.addCookie(ck_pw);
                return RestResponse.success("【三天内将自动登录】欢迎登录，亲爱的 " + loginUser.getUsername()).toString();
            }
            return RestResponse.success("欢迎登录，亲爱的 " + loginUser.getUsername()).toString();
        }
    }

    /**
     * 自动登录
     **/
    @PostMapping("/autoLogin")
    public RestResponse<String> autoLogin(HttpServletRequest request, HttpSession session){
        String usercode = "", password = "";
        for (Cookie cookie : request.getCookies()) {
            if("usercode".equals(cookie.getName()))
                usercode = cookie.getValue();
            else if ("password".equals(cookie.getName()))
                password = cookie.getValue();
        }
        // 如果没有登录
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isAuthenticated()){
            // 登录试试
            User user = new User();
            user.setUsercode(usercode);
            user.setPassword(password);
            User loginUser = userService.login(user);
            if(loginUser!=null){
                session.setAttribute("loginUser", loginUser);
                return RestResponse.success(String.format("欢迎回来，亲爱的[ %s ]", loginUser.getUsername()));
            }
        }
        return RestResponse.fail("自动登录失败");
    }


    /**
     * 查找用户是否存在
     * @param user 用户
     * @return 返回用户是否存在
     */
    @PostMapping("/verify")
    public RestResponse<String> verify(User user){
        boolean result = userService.verifyCodeExisted(user);
        return result ?
                RestResponse.success()
                : RestResponse.fail();
    }
    @PostMapping("/verifyEmailCode")
    public String verifyEmailCode(User user, @RequestParam String captcha, HttpSession session){
        if(user.getUsercode() == null){
            User loginUser = (User) session.getAttribute("loginUser");
            user.setUsercode(loginUser.getUsercode());
        }
        // 验证码不正确直接返回
        if(!userService.verifyEmailCode(user, captcha))
            return RestResponse.fail("验证码错误!").toString();
        else
            return RestResponse.success("验证成功!").toString();
    }
    @PostMapping("/update/self")
    public String saveBaseSelf(User user, UserAddressCodeVo addressCodeVo, HttpSession session){
        // 获取登录用户
        User loginUser = (User) session.getAttribute("loginUser");
        assert user != null && loginUser != null;
        // 确保账号一致
        if(!user.getUsercode().equals(loginUser.getUsercode())){
            return RestResponse.fail("提示: 保存的用户账号和登录账号不一致!").toString();
        }
        // 赋值用户的ID
        user.setId(loginUser.getId());
        user.setImg(loginUser.getImg());
        user.setRole(loginUser.getRole());
        boolean result = userService.saveBaseById(user, addressCodeVo);
        // 更新 session 的用户
        if(result){
            session.setAttribute("loginUser", user);
            return  RestResponse.success("保存成功!").toString();
        } else
            return RestResponse.fail("保存失败.").toString();
    }
    @PostMapping("/update/{id}")
    public RestResponse<String> saveBaseBy(User user, UserAddressCodeVo addressVo){
        return userService.saveBaseById(user, addressVo) ?
                RestResponse.success("修改成功!") :
                    RestResponse.fail("修改失败.");
    }
    @PostMapping("/oss")
    public String getDefaultImages(){
        List<String[]> list = ossService.getDefaultHeadImgLink();
        return list != null ?
                RestResponse.success(list).toString():
                RestResponse.fail("获取失败").toString();
    }


    /**
     * 用户修改自己的默认头像
     * @param user
     * @param imgUrl
     * @param session
     * @return
     */
    @PostMapping("/img/self")
    public RestResponse<String> saveUserHeadImgBySelf(@RequestParam String imgUrl, HttpSession session){
        User loginUser = (User) session.getAttribute("loginUser");
        int result = userService.saveImgByCode(loginUser.getUsercode(), imgUrl);
        // 若是修改自己的头像，就更新 session，方便前端展示
        if(result == 1){
            loginUser.setImg(imgUrl);
            session.setAttribute("loginUser", loginUser);
        }
        return result == 1 ?
                RestResponse.success("修改成功!") :
                RestResponse.fail("修改失败.");
    }

    /**
     * 修改指定ID的用户为默认头像
     * @param user
     * @param imgUrl
     * @param session
     * @return
     */
    @PostMapping("/img/{userId}")
    public String saveUserHeadImgById(@PathVariable Long userId, @RequestParam String imgUrl, HttpSession session){
        User loginUser = (User) session.getAttribute("loginUser");
        int result = userService.saveImgById(userId, imgUrl);
        if(result == 1 ){
            // 判断修改的用户是否为当前登录的用户
            if (userId.equals(loginUser.getId())){
                loginUser.setId(userId);
                session.setAttribute("loginUser", loginUser);
            }
        }
        return result == 1 ?
                RestResponse.success("修改成功!").toString():
                RestResponse.fail("修改失败.").toString();
    }

    /////////////////////////// 保存自定义的头像
    @PutMapping("/img/self")
    public String saveUserHeadImgCustom(@RequestParam(required = false) User user, @RequestParam String img64Base, HttpSession session){
        // 标记是否修改自己的头像
        boolean self = false;
        if(user == null || user.getUsercode() == null){
            user = (User) session.getAttribute("loginUser");
            self = true;
        }
        assert user.getUsercode() != null: "用户的账号不能为空";
        // 调用 API 上传头像
        OssUploadResult ossResult = ossService.upload(user.getUsercode(), img64Base);
        int result = 0;
        if(!"".equals(ossResult.getImgUrl()))
            result = userService.saveImgByCode(user.getUsercode(), ossResult.getImgUrl());
        // 若是修改自己的头像，就更新 session，方便前端展示
        if(result == 1 && self){
            user.setImg(ossResult.getImgUrl());
            session.setAttribute("loginUser", user);
        }
        return result == 1 ?
                RestResponse.success("修改成功!").toString():
                RestResponse.fail("修改失败.").toString();
    }

    @PutMapping("/img/{userId}")
    public RestResponse<String> saveUserHeadImgCustomById(@PathVariable Long userId, @RequestParam String img64Base, HttpSession session){
        // 标记是否修改自己的头像
        User loginUser = (User) session.getAttribute("loginUser");
        // 调用 API 上传头像
        OssUploadResult ossResult = ossService.uploadById(userId, img64Base);
        int result = 0;
        if(!"".equals(ossResult.getImgUrl()))
            result = userService.saveImgById(userId, ossResult.getImgUrl());
        // 若是修改自己的头像，就更新 session，方便前端展示
        if(result == 1 && userId.equals(loginUser.getId())){
            loginUser.setImg(ossResult.getImgUrl());
            session.setAttribute("loginUser", loginUser);
        }
        return result == 1 ?
                RestResponse.success("修改成功!"):
                    RestResponse.fail("修改失败.");
    }

    @PostMapping("/updatePassword")
    public RestResponse<String> saveUserPassword(User user, HttpSession session){
        boolean flag = false;
        if(user.getUsercode() == null){
            String pw = user.getPassword();
            user = (User) session.getAttribute("loginUser");
            user.setPassword(pw);
            flag = true;
        }
        return userService.savePassword(user, flag) ?
                RestResponse.success("修改成功!") :
                    RestResponse.fail("修改失败.") ;
    }

    @PostMapping("/updateEmail")
    public String updateEmail(User user, String captcha, HttpSession session){
        User loginUser = (User) session.getAttribute("loginUser");
        user.setId(loginUser.getId());
        user.setUsercode(loginUser.getUsercode());
        boolean result = userService.verifyEmailCode(user, captcha);
        if(!result)
            return RestResponse.fail("邮箱验证码错误").toString();
        return userService.saveEmail(user) ?
                RestResponse.success("修改成功!").toString():
                RestResponse.fail("修改失败").toString();
    }


    @PostMapping("/select/{ids}")
    public RestResponse<List<User>> QueryUserByIds(@PathVariable List<Long> ids){
        return RestResponse.success(userService.queryWithRoleByIds(ids));
    }
    @PostMapping("/selectCount")
    public RestResponse<Long> getCountUser(){
        return RestResponse.success(userService.count());
    }

    /**
     * 查询所有用户所处的省份信息，返回列表类型的省份名称和统计数
     * @return
     */
    @PostMapping("/select/province/all")
    public RestResponse<List<UserProvinceCountVo>> queryUser(){
        return RestResponse.success(userService.getListWithProvinceCount());
    }
    /**
     * 找回密码
     */
    @PostMapping("/retrieve")
    public RestResponse<String> retrieveUser(User user, String emailCode){
        return userService.retrieve(user, emailCode) ?
                RestResponse.success("重置成功, 请进行登录!")
                    : RestResponse.fail("重置失败, 请检查邮箱验证码是否正确");
    }

    // 删除用户
    @DeleteMapping("/delete/{userIds}")
    public RestResponse<String> removeUser(@PathVariable List<Long> userIds){
        return userService.removeByIds(userIds) ?
                RestResponse.success("删除成功!")
                    : RestResponse.success("删除失败.");
    }
}
